﻿/*
   Copyright 2012 University of Southampton

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

using System;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using System.Collections.Generic;
using System.Linq;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.IO;
using System.Web.UI.HtmlControls;
using uk.ac.soton.ses.DAL;
using System.Web;
using uk.ac.soton.ses.WebControls;

namespace uk.ac.soton.ses.layouts
{
    public partial class StatsFileViewer : LayoutsPageBase
    {
        //Unneeded?
        private List<int> requestedFieldNos = null;
        private List<int> requestedDatasetNos = null;

        private bool IsInitialised = false;
        private ExperimentDataFile dataFile = null;
        //private int linecount = -1;
        //Dictionary<int, string> dsTitleDict = null;
        //Dictionary<int, string> fieldDict = null;
        private char delim;
        private FileParser_Stats parsedFile = null;

        MaterialsMetadataContext dbcontext = null;

        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);

            this.dbcontext = HttpContext.Current.GetMaterialsDBContext();

            this.lst_Datasets.SelectedIndexChanged += new EventHandler(lst_Datasets_SelectedIndexChanged);
            this.lst_Fields.SelectedIndexChanged += new EventHandler(lst_Fields_SelectedIndexChanged);
            this.txt_Delimeter.TextChanged+=new EventHandler(txt_Delimeter_TextChanged);
            this.btn_SaveReport.Click+=new EventHandler(btn_SaveReport_Click);
            this.btn_SaveAsMetadata.Click += new EventHandler(btn_SaveAsMetadata_Click);

            string dataFileIDString = Page.Request.QueryString["DataFileID"];
            string delimStr = Page.Request.QueryString["Delim"] ?? "\t";
            string[] requestedFieldNosStrings = Page.Request.QueryString.GetValues("FieldNo") ?? new string[0];
            string[] requestedDatasetNosStrings = Page.Request.QueryString.GetValues("DatasetNo") ?? new string[0];

            int dataFileID;

            if (   !int.TryParse(dataFileIDString, out dataFileID)
                || delimStr.Length < 1
               )
            {
                return;
            }

            this.delim = delimStr[0];
            this.dataFile = dbcontext.GetExperimentDataFileByID(dataFileID);
            this.LoadFile();
            this.SetRequestedFields(requestedFieldNosStrings);
            this.SetRequestedDatasets(requestedDatasetNosStrings);
            this.IsInitialised = true;
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            if (this.IsInitialised)
            {
                this.CreateTable();

                if (!this.IsPostBack)
                {
                    this.lbl_LineCount.Text = this.parsedFile.LineCount.ToString();

                    this.CreateFieldSelectionList();

                    this.txt_Delimeter.Text = System.Text.RegularExpressions.Regex.Escape(this.delim.ToString());
                }
            }
        }

        private void lst_Fields_SelectedIndexChanged(object sender, EventArgs e)
        {
            this.requestedFieldNos = this.GetNewSelectionFromList(this.lst_Fields);
            this.RedirectToNewUrl();
        }

        private void lst_Datasets_SelectedIndexChanged(object sender, EventArgs e)
        {
            this.requestedDatasetNos = this.GetNewSelectionFromList(this.lst_Datasets);
            this.RedirectToNewUrl();
        }

        private void btn_SaveReport_Click(object sender, EventArgs e)
        {
            string reportUrl = this.Page.Request.Url.AbsoluteUri;

            if (!this.dataFile.ExperimentReference.IsLoaded)
            {
                this.dataFile.ExperimentReference.Load();
            }

            Experiment exp = this.dataFile.Experiment;
            if (exp != null)
            {
                //Add our new report parameter
                ExperimentParameter savedReportParam = exp.AddReportParameter(this.dbcontext, reportUrl);
                //ExperimentParameter savedReportParm = exp.SaveParameterValue(this.dbcontext, "Saved report " + DateTime.Now, reportUrl,true);

                //bool resultokay = exp.AddToReportParameters(savedReportParm, this.dbcontext);

                if (savedReportParam != null)
                //if (resultokay)
                {
                    //Save the changes
                    dbcontext.SaveChanges();

                    //Report what we did to the user
                    HDCSharedWebFunctions.AddMessageLabel("Report saved to experiment " + exp.ID, this.ReportButtons);
                }
                //Look up the reports parent parameter
                //ExperimentParameter reportsParam = exp.LookupParameter("Saved reports");

                //if (reportsParam == null)
                //{
                //    reportsParam = exp.SaveParameterValue(this.dbcontext, "Saved reports", "", true);
                //}

                //Move the report parameter under the reports parent parameter
                //reportsParam.AddChildParameter(this.dbcontext, savedReportParm);

                //Save the new parameter link
                //dbcontext.SaveChanges();
            }
        }

        private void btn_SaveAsMetadata_Click(object sender, EventArgs e)
        {
            this.dataFile.ImportAsStatsFile(this.dbcontext, true, this.delim, this.requestedFieldNos, this.requestedDatasetNos);
        }

        private void txt_Delimeter_TextChanged(object sender, EventArgs e)
        {
            string delimStr = this.txt_Delimeter.Text;
            if (delimStr.Length >= 1)
            {
                //If the user has entered a slash to begin with then we must unescape it to find out the character they were asking for
                //This only applies if they have entered 2 chars (e.g. \n) or more (we will just ignore the remaining chars)
                if (delimStr.Length >= 2 && delimStr[0] == '\\')
                {
                    delimStr = System.Text.RegularExpressions.Regex.Unescape(delimStr);
                }

                this.delim = delimStr[0];
            }
            else
            {
                this.delim = '\t';
            }
            this.RedirectToNewUrl();
        }

        private void RedirectToNewUrl()
        {
            string datafilestr = "DataFileID=" + dataFile.ID;
            string fieldsstr = (this.requestedFieldNos.Count > 0 ? "&" + string.Join("&", this.requestedFieldNos.Select(f => string.Format("FieldNo={0}", f)).ToArray()) : "");
            string datasetsstr = (this.requestedDatasetNos.Count > 0 ? "&" + string.Join("&", this.requestedDatasetNos.Select(f => string.Format("DatasetNo={0}", f)).ToArray()) : "");
            string delimStr = "&delim=" + HttpUtility.UrlEncode(this.delim.ToString());
            string redirectUrl = string.Format("{0}?{1}{2}{3}{4}", this.Page.Request.Url.GetLeftPart(UriPartial.Path), datafilestr, fieldsstr, datasetsstr, delimStr);
            this.Response.Redirect(redirectUrl);
        }

        private void CreateFieldSelectionList()
        {
            //Clear the lists
            this.lst_Fields.Items.Clear();
            this.lst_Datasets.Items.Clear();

            //Populate the lists
            this.lst_Fields.Items.AddRange(this.parsedFile.FieldNames.Select(kvp => new ListItem(kvp.Value, kvp.Key.ToString())).ToArray());
            this.lst_Datasets.Items.AddRange(this.parsedFile.DatasetNames.Select(kvp => new ListItem(kvp.Value, kvp.Key.ToString())).ToArray());

            //Check the fields that were requested
            foreach (int reqField in requestedFieldNos)
            {
                this.lst_Fields.Items.FindByValue(reqField.ToString()).Selected = true;
            }
            foreach (int reqField in this.requestedDatasetNos)
            {
                this.lst_Datasets.Items.FindByValue(reqField.ToString()).Selected = true;
            }
        }


        private void CreateTable()
        {
            foreach (KeyValuePair<int, string> kvp in parsedFile.DatasetNames)
            {
                //Only display the datasets that were requested
                if (requestedDatasetNos.Count == 0 || requestedDatasetNos.Contains(kvp.Key))
                {
                    //Create a DIV for us to add data for each column
                    HtmlGenericControl datasetdiv = new HtmlGenericControl("div");
                    this.ReportResults.Controls.Add(datasetdiv);
                    datasetdiv.Style.Add("float", "left");

                    //Create a heading and add it to the div
                    HtmlGenericControl datasethead = new HtmlGenericControl("h1");
                    datasetdiv.Controls.Add(datasethead);
                    datasethead.InnerHtml = kvp.Value;

                    //Create the list of field values, adding them to the div
                    foreach (KeyValuePair<int, string> fieldvalue in parsedFile.FieldValues[kvp.Key])
                    {
                        //Only display the fields that were requested
                        if (requestedFieldNos.Count == 0 || requestedFieldNos.Contains(fieldvalue.Key))
                        {
                            HtmlGenericControl vardetails = new HtmlGenericControl("p");
                            datasetdiv.Controls.Add(vardetails);
                            vardetails.InnerHtml = parsedFile.FieldNames[fieldvalue.Key] + " = " + fieldvalue.Value;
                        }
                    }
                }
            }
        }

        private void LoadFile()
        {
            this.parsedFile = new FileParser_Stats(dataFile.GetFullPath(), this.delim);
        }

        private void SetRequestedFields(string[] requestedFieldNos)
        {
            List<int> newFieldList = new List<int>();

            foreach(string reqField in requestedFieldNos)
            {
                foreach(KeyValuePair<int,string> fieldKVP in this.parsedFile.FieldNames)
                {
                    if (fieldKVP.Key.Equals(Convert.ToInt32(reqField)) && !newFieldList.Contains(fieldKVP.Key))
                    {
                        newFieldList.Add(fieldKVP.Key);
                        break;
                    }
                }
            }

            this.requestedFieldNos = newFieldList;
        }

        private void SetRequestedDatasets(string[] requestedDSNos)
        {
            List<int> newDSList = new List<int>();

            foreach (string reqDS in requestedDSNos)
            {
                foreach (KeyValuePair<int, string> fieldKVP in this.parsedFile.DatasetNames)
                {
                    if (fieldKVP.Key.Equals(Convert.ToInt32(reqDS)) && !newDSList.Contains(fieldKVP.Key))
                    {
                        newDSList.Add(fieldKVP.Key);
                        break;
                    }
                }
            }

            this.requestedDatasetNos = newDSList;
        }

        private List<int> GetNewSelectionFromList(CheckBoxList cblist)
        {
            List<int> newFieldList = new List<int>();

            foreach (ListItem listitem in cblist.Items)
            {
                if (listitem.Selected)
                {
                    newFieldList.Add(int.Parse(listitem.Value));
                }
            }

            return newFieldList;
        }

    }
}
